<?php
namespace Tlf\Scrawl\Ext\MdVerb;
class Ast {
public \Tlf\Scrawl $scrawl;
public function __construct($scrawl){
$this->scrawl = $scrawl;
}
/**
* Get an ast & optionally load a custom template for it
*
* @usage @ast(class.ClassName.methods.docblock.description, ast/default)
*/
public function get_markdown($key, $template='ast/default'){
$value = $this->get_ast($key);
$template = $this->scrawl->get_template($template, [$key, $value, $this]);
return $template;
}
/**
* @param $key a dotproperty like `class.ClassName.methods.MethodName.docblock.description`
* @param $length the number of dots in the dotproperty to traverse. -1 means all
*/
public function get_ast(string $key, int $length=-1){
$parts = explode('.',$key);
if ($length!=-1){
$parts = array_slice($parts, 0,$length);
}
$group = array_shift($parts);
$class = array_shift($parts);
$ast = $this->scrawl->get('ast', $group.'.'.$class);
$stack = $group.'.'.$class;
$next = $ast;
foreach ($parts as $p){
$current = $next;
$stack .= '.'.$p;
// echo "\n\n$stack";
if (!isset($current[$p])&&is_array($current)){
foreach ($current as $i=>$item){
if (!is_numeric($i))continue;
// echo "\n\n".$p."::";
// echo $item['name']."\n\n";
if ($item['name']==$p){
$next = $item;
continue 2;
}
}
print_r($current);
$this->scrawl->warn("Ast Not Found", "Can't load '$key'. Failed at '$current.$p'");
return null;
break;
echo "\n\nFailed at ".$stack;
echo "\n\nsomething went wrong\n\n";
exit;
} else if (!isset($current[$p])){
$this->scrawl->warn("Ast Not Found", "Can't load '$key'. Failed at '$p'");
return null;
echo "\n\ncan't get next item\n\n";
exit;
}
$next = $current[$p];
}
// exit;
return $next;
}
public function getVerbs(): array{
return [
'ast'=>'verbAst', //alias for @ast_class()
'classMethods'=>'getClassMethodsTemplate',
'ast_class'=> 'getAstClassInfo',
];
}
/**
*
* @param $fqn The fully qualified name, like a class name or function with its namespace
* @param $dotProperty For class, something like 'methods.methodName.docblock' to get a docblock for the given class.
*
* @example @ast(\Tlf\Scrawl\Ext\MdVerb\Ast, methods.getAstClassInfo.docblock)
* @mdverb ast
*
*/
public function getAstClassInfo(array $info, string $fqn, string $dotProperty){
// @ast(class,Phad\Test\Documentation,methods.testWriteAView.docblock)
$class = $this->scrawl->getOutput('astClass', $fqn);
// var_dump(array_keys($this->scrawl->getOutputs('astClass')));
if ($class == 'null') return "class '$fqn' not found in ast.";
$propStack = explode('.', $dotProperty);
$head = $class;
if (!is_array($head)){
$file = $info['file']->path;
// $this->scrawl->error('@ast or @ast_class in '.$file,'requires "astClass" output for fqn "'.$fqn.'" to be an array, but a '. gettype($class).' was returned.');
$this->scrawl->error("@ast($fqn, $dotProperty) failed", 'in '.$file);
return "@ast($fqn) failed";
}
foreach ($propStack as $prop){
if ($prop=='*'){
return print_r($head,true);
}
if (!isset($head[$prop])){
$options = [];
foreach ($head as $key=>$value){
if (is_numeric($key) && ($value['name']??null)==$prop){
$head = $head[$key];
continue 2;
} else if (is_numeric($key) && isset($value['name'])){
$options[] = $value['name'];
}
}
$options = array_merge($options, array_keys($head));
$msg = "Cannot find '$prop' part of '$dotProperty' on '$fqn'. You may try one of: ". implode(", ", $options);
$this->scrawl->error('@ast or @ast_class', $msg);
return $msg;
}
$head = $head[$prop];
}
if (is_array($head)){
if (isset($head['body']))return $head['body'];
else if (isset($head['description']))return $head['description'];
else if (isset($head['src']))return $head['src'];
$msg="Found an array for '$dotProperty' on '$fqn' with keys: ".implode(", ", array_keys($head));
$this->scrawl->error('@ast or @ast_class', $msg);
return $msg;
}
return $head;
}
/**
*
* @return string replacement
*/
public function verbAst($info, $className, $dotProperty){
//
// This method not currently functional. Ugggh!!!
//
// $parts = explode('.', $classDotThing);
// $class = array_shift($parts);
// return $this->getAstClassInfo($info, $class, 'method.'.implode('.',$parts));
return $this->getAstClassInfo($info, $className, $dotProperty);
// $key = $class;
// var_dump($key);
// $output = $this->scrawl->getOutput('api',$key);
//
// if (trim($output)=='')return "--ast '${class}' not found--";
//
// return $output;
}
public function getClassMethodsTemplate($verb, $argListStr, $line){
if ($verb!='classMethods')return;
$args = explode(',', $argListStr);
$className = $args[0];
$visibility = '*';
if (isset($args[1])){
$visibility = trim($args[1]);
}
$class = $this->scrawl->getOutput('astClass', $className);
$template = dirname(__DIR__,2).'/Template/classMethods.md.php';
ob_start();
require($template);
$final = ob_get_clean();
return $final;
}
}